package com.project.restaurant.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.project.restaurant.common.api.ResponseResult;
import com.project.restaurant.common.api.ServiceStateCode;
import com.project.restaurant.common.exception.ServiceException;
import com.project.restaurant.common.util.FileOptionUtil;
import com.project.restaurant.mapper.UserMapper;
import com.project.restaurant.pojo.User;
import com.project.restaurant.redis.key.RedisKey;
import com.project.restaurant.redis.service.RedisClient;
import com.project.restaurant.thirdpart.bo.template.CodeTemplate;
import com.project.restaurant.thirdpart.mail.Mail;
import com.project.restaurant.thirdpart.mail.TemplateMail;
import com.project.restaurant.user.dto.RegisterInfo;
import com.project.restaurant.user.feign.FastDFSService;
import com.project.restaurant.user.feign.MailService;
import com.project.restaurant.user.service.RegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

@Service
public class RegisterServiceImpl  implements RegisterService{


    @Resource
    private UserMapper userMapper;

    @Resource
    RedisClient redisClient;

    @Resource
    MailService mailService;

    @Autowired
    FastDFSService fastDFSService;

    @Override
    public boolean selectByAccount(String account) {
        boolean exists = userMapper.exists(new LambdaQueryWrapper<User>().eq(User::getAccount, account));
        if (exists){
            throw new ServiceException(ServiceStateCode.EXIST_USER);
        }
        return true;
    }

    @Override
    public boolean selectPhone(String userPhone) {
        boolean exists = userMapper.exists(new LambdaQueryWrapper<User>().eq(User::getUserPhone, userPhone));
        if (exists){
            throw new ServiceException(ServiceStateCode.EXIST_EMAIL);
        }
        return true;
    }

    @Override
    public boolean selectEmail(String email) {
        boolean exists = userMapper.exists(new QueryWrapper<User>().eq("user_email", email));
        if (exists){
            throw new ServiceException(ServiceStateCode.EXIST_EMAIL);
        }
        return true;
    }

    /**
     * @description: 发送注册验证码
     * @author: 肖友涵
     * @date: 2022/10/18 11:07
     * @param email
     * @return: com.project.restaurant.common.api.ServiceReturn<java.lang.Boolean>
     **/
    @Override
    public boolean sendRegisterAuthCodeToEmail(String email) {
        //判断是否已经向目标邮箱发送过邮件了
        String code = (String) redisClient.get(RedisKey.EMAIL_REGISTER_AUTH_CODE + email);
        if (code != null) {
            throw  new ServiceException(ServiceStateCode.EMAIL_ALREADY_SEND);
        }

        //查看邮箱对应的用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_email",email);
        boolean exists = userMapper.exists(queryWrapper);

        if(!exists){
            //发送邮箱
            String authCode = String.valueOf((int) (Math.random() * 900000)+100000);
            Mail templateMail = new TemplateMail(email,"用户注册",
                    new CodeTemplate(email,authCode,"mail_register_auth_code"));
            ResponseResult<Boolean> result = mailService.sendTemplateMail(templateMail);
            redisClient.setEx(RedisKey.EMAIL_REGISTER_AUTH_CODE+email,authCode,120);
            if (result.isSuccess()) {
                return true;
            }
            throw new ServiceException(ServiceStateCode.SEND_FAILURE);
        }

        throw new ServiceException(ServiceStateCode.EXIST_EMAIL);
    }

    @Transactional
    @Override
    public boolean register(RegisterInfo registerInfo) {
        User user = registerInfo.getUser();
        if (user==null){
            throw  new ServiceException(ServiceStateCode.FAIL_TO_REGISTER);
        }
        try{
            //当打包成JAR包时，无法通过该地址查找到文件对象，那么在JAR包中，如何读取静态文件呢？
            //            byte[] read = FileOptionUtil.read(RegisterServiceImpl.class.getClassLoader().getResource("").getPath());
            //通过流方式获取
            String defaultAvatarPath = "static/img/defaultAvatar.jpg";
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(defaultAvatarPath);
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuffer buffer = new StringBuffer();
            String line = null;
            while ((line = reader.readLine()) != null){
                buffer.append(line);
            }
            ResponseResult<String> responseResult = fastDFSService.fileUpload(buffer.toString().getBytes(StandardCharsets.UTF_8));
            if(!responseResult.isSuccess()){
                throw new ServiceException(ServiceStateCode.FAILURE);
            }
            user.setUserAvatar(responseResult.getData());
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(ServiceStateCode.FAILURE);
        }

        int insert = userMapper.insert(user);
        if (insert != 1){
            throw new ServiceException(ServiceStateCode.FAIL_TO_REGISTER);
        }
        redisClient.delKey(RedisKey.EMAIL_REGISTER_AUTH_CODE+user.getUserEmail());
        return true;
    }


    @Override
    public boolean checkRegisterInfo(RegisterInfo registerInfo){
        //查看注册的账户是否已经存在了
        selectByAccount(registerInfo.getAccount());
        String email = registerInfo.getBindingEmail().getEmail();
        String code = registerInfo.getBindingEmail().getAuthCode();
        //查看注册的邮箱是否已经存在了
        selectEmail(email);

        //进行验证码校验
        if (registerInfo.getBindingEmail() != null) {
            String o = (String) redisClient.get(RedisKey.EMAIL_REGISTER_AUTH_CODE + email);
            if(o==null){
                throw  new ServiceException(ServiceStateCode.AUTH_CODE_TIMEOUT);
            }
            if (!code.equals(o)){
                throw  new ServiceException(ServiceStateCode.AUTH_CODE_NO_MATCH);
            }
        }
        return true;
    }

}
